﻿using System.Windows.Threading;
using CSharp.Libs.Koc;
using System;
using System.Windows.Input;
using CSharp.Libs.Koc.Models;
using System.Threading;
using System.Collections.ObjectModel;
using System.Collections;
using CSharp.Libs.Koc.ItemClasses;
using System.Collections.Generic;
using CSharp.Libs.Koc.KernelModels;
using System.Text;

namespace CSharp.Libs.WPF.UserControls
{
    public class KocHireKnightViewModel : ViewModelBase//, IDisposable
    {
        #region declarations
        private Dispatcher _DISP = null;
        private Kernel _KRNL = null;
        private KocKernel2ViewModel _KK2VM = null;
        private SeekKnight _SK = null;
        private PostHandler _PH = null;
        private Random _RND = null;
        private RelayCommand _rcHireKnights = null;

        private ObservableCollection<HireKnightItem> _ocKnightsToHireList = new ObservableCollection<HireKnightItem>();
        private ObservableCollection<CityItem> _ocCityList = new ObservableCollection<CityItem>();

        private CityItem _selectedCity = null;

        private string _strSelectedCityId = "";
        private bool _fHiringKnights = false;
        private bool _fCanHireKnights = false;
        private int _intKnightsToHire = 1;

        #region events
        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="leea"></param>
        /// <history>created  09.03.2012</history>
        public delegate void LogEntryEventHandler(object sender, LogEntryEventArgs leea);
        public event LogEntryEventHandler LogEntry;
        private void ThrowLogEntryEvent(
            LogEntryEventArgs leea)
        {
            if (LogEntry != null)
            {
                LogEntry(this, leea);
            }
        }
        #endregion
        #endregion



        #region constructor / finalizer
        public KocHireKnightViewModel(
            Dispatcher DISP,
            Kernel KRNL,
            KocKernel2ViewModel KK2VM)
        {
            _DISP = DISP;
            _KRNL = KRNL;
            _KK2VM = KK2VM;
            _SK = new SeekKnight(_KRNL);
            _PH = new PostHandler(_KRNL);

            _initRandom();

            _KRNL.SC.SeedReceived += new SeedCollector.SeedReceivedEventHandler(SC_SeedReceived);

            _KK2VM.AfterUserChange += new KocKernel2ViewModel.AfterUserChangeEventHandler(_KK2VM_AfterUserChange);
            _KK2VM.AfterServerChange += new KocKernel2ViewModel.AfterServerChangeEventHandler(_KK2VM_AfterServerChange);

            _SK.EndSeekKnights += new SeekKnight.EndSeekKnightsEventHandler(_SK_EndSeekKnights);

            _PH.TimerStarted += new PostHandler.TimerStartedEventHandler(_PH_TimerStarted);
            _PH.TimerStopped += new PostHandler.TimerStoppedEventHandler(_PH_TimerStopped);
        }

        //public  void Dispose()
        //{
        //    Dispose(true);
        //    GC.SuppressFinalize(this);
        //}

        //protected virtual void Dispose(bool disposing)
        //{
        //    if (disposing)
        //    {             
        //        // get rid of managed resources
        //        _KK2VM.AfterUserChange -= _KK2VM_AfterUserChange;
        //        _KK2VM.AfterServerChange -= _KK2VM_AfterServerChange;

        //        _KK2VM = null;
        //        _KRNL = null;
        //        _DISP = null;
        //    }            
        //    // get rid of unmanaged resources     
        //}

        //~KocHireKnightViewModel()
        //{
        //    Dispose(false);
        //}
        #endregion
        
        
        
        #region event handling
        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="srea"></param>
        /// <history>created  27.05.2012</history>
        void SC_SeedReceived(object sender, Koc.KernelModels.SeedReceivedEventArgs srea)
        {
            //build city list
            _createCityList();

            //seek free knights
            _seekFreeKnights();

            //check if can hire knights
            _checkCanHireKnights();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="ucea"></param>
        /// <history>created  26.05.2012</history>
        void _KK2VM_AfterUserChange(object sender, UserChangeEventArgs ucea)
        {
            //build city list
            _createCityList();

            //seek free knights
            _seekFreeKnights();

            //check if can hire knights
            _checkCanHireKnights();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="scea"></param>
        /// <history>created  26.05.2012</history>
        void _KK2VM_AfterServerChange(object sender, ServerChangeEventArgs scea)
        {
            //build city list
            _createCityList();

            //seek free knights
            _seekFreeKnights();

            //check if can hire knights
            _checkCanHireKnights();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <history>created  26.05.2012</history>
        void _SK_EndSeekKnights(object sender)
        {
            //put together list of knights to hire
            _createHireList();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <history>created  10.06.2012</history>
        void _PH_TimerStopped(object sender)
        {
            _checkCanHireKnights();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <history>created  10.06.2012</history>
        void _PH_TimerStarted(object sender)
        {
            _checkCanHireKnights();
        }
        #endregion
        
        
        
        #region private functions
        /// <summary>
        /// 
        /// </summary>
        /// <history>created  26.02.2012</history>
        /// <history>modified 14.03.2012: changed structure</history>
        private void _hireKnights()
        {
            //try
            //{
                //set switch
                _BeginHiring();

                //check if can hire knights to disable button 
                _checkCanHireKnights();

                //start hiring
                _startHiring();

                //end hiring
                _EndHiring();
            //}
            //catch(Exception ex)
            //{
            //    _KRNL.EC.AddException(ex, this.ToString(), _KRNL.EC.Tools.GetCurrentMethodName());
            //}
        }

        /// <summary>
        /// 
        /// </summary>
        /// <history>created  14.03.2012</history>
        private void _seekFreeKnights()
        {
            //try
            //{
                //check if generator is initialized and User and Server selected
                if (PhpCommandGenerator.IsInitialized &&
                    _KK2VM.SelectedUser != null &&
                    _KK2VM.ServerId > 0)
                {
                    //first seek knights
                    Thread thr = new Thread((ParameterizedThreadStart)delegate
                    {
                        _SK.SeekKnights(18, _KK2VM.ServerId, _KK2VM.SelectedUser.FbUid);
                    });
                    thr.Start();
                }
            //}
            //catch (Exception ex)
            //{
            //    _KRNL.EC.AddException(ex, this.ToString(), _KRNL.EC.Tools.GetCurrentMethodName());
            //}
        }

        /// <summary>
        /// 
        /// </summary>
        /// <history>created  26.02.2012</history>
        private void _createHireList()
        {
            //try
            //{
                //clear list
                _clearKnights();

                //check if desired Knightcount suits Knightcount
                if (PhpCommandGenerator.IsInitialized &&
                    _KK2VM.SelectedUser != null &&
                    _KK2VM.ServerId > 0)
                {
                    if (_intKnightsToHire >
                    (_SK.KocActiveFbFriends.Count + _SK.KocInactiveFbFriends.Count))
                    {
                        //message user das zuviel gewünscht is

                        //set Knights To Hire to Max
                        _intKnightsToHire = _SK.KocActiveFbFriends.Count + _SK.KocInactiveFbFriends.Count;
                        OnPropertyChanged("KnightsToHire");
                    }
                }

                //prepare counter
                int intCount = 1;

                //cycle through Koc active FB friends
                foreach (SeekKnightItem SKI in _SK.KocActiveFbFriends)
                {
                    //check and set counter
                    if (intCount > _intKnightsToHire) { break; }
                    intCount++;

                    //Add Knight
                    HireKnightItem HKI = new HireKnightItem(SKI);
                    _AddKnight(HKI);
                }

                //cycle through Koc inactive FB friends
                foreach (SeekKnightItem SKI in _SK.KocInactiveFbFriends)
                {
                    //check and set counter
                    if (intCount > _intKnightsToHire) { break; }
                    intCount++;

                    //Add Knight
                    HireKnightItem HKI = new HireKnightItem(SKI);
                    _AddKnight(HKI);
                }
            //}
            //catch(Exception ex)
            //{
            //    _KRNL.EC.AddException(ex, this.ToString(), _KRNL.EC.Tools.GetCurrentMethodName());
            //}
        }

        /// <summary>
        /// 
        /// </summary>
        /// <history>created  28.02.2012</history>
        private void _createCityList()
        {
            //try
            //{
                //clear citylist
                _clearCities();

                //check if user and server are selected
                if (_KK2VM.SelectedUser != null &&
                   _KK2VM.ServerId > 0)
                {
                    //check if seed was received
                    string strKey=_KRNL.SC.GetKey(_KK2VM.SelectedUser.FbUid, _KK2VM.ServerId.ToString());
                    if (_KRNL.SC.Seeds.ContainsKey(strKey))
                    {
                        //build city list
                        SeedHolder SH = new SeedHolder(_KRNL, _KRNL.SC.Seeds[strKey] as Hashtable);

                        foreach (KeyValuePair<string, CityItem> KVP in SH.Cities)
                        {
                            _AddCity(KVP.Value);
                        }
                    }
                }
            //}
            //catch (Exception ex)
            //{
            //    _KRNL.EC.AddException(ex, this.ToString(), _KRNL.EC.Tools.GetCurrentMethodName());
            //}
        }

        /// <summary>
        /// 
        /// </summary>
        /// <history>created  09.03.2012</history>
        private void _startHiring()
        {
            //try
            //{

            for (int intIDX = 1; intIDX <= _intKnightsToHire; intIDX++)
            {
                PostHandlerItem PHI = new PostHandlerItem(_KRNL.InternalUID);
                PHI.pcCommand = PhpCommandGenerator.GetPhpCommand(_KRNL.EC, PhpCommands.hireSpecialKnight, _KK2VM.ServerId, _KK2VM.SelectedUser.FbUid);

                //set params
                if (PHI.pcCommand.Parameters.ContainsKey(PhpCommandParameters.CID))
                {
                    //PHI.pcCommand.Parameters[PhpCommandParameters.CID] = SelectedCity.CityID.ToString();
                    PHI.pcCommand.Parameters[PhpCommandParameters.CID] = SelectedCityId;
                }
                else
                {
                    PHI.pcCommand.Parameters.Add(PhpCommandParameters.CID, SelectedCity.CityID.ToString());
                }

                if (PHI.pcCommand.Parameters.ContainsKey(PhpCommandParameters.KNAME))
                {
                    PHI.pcCommand.Parameters[PhpCommandParameters.KNAME] = "Ritter" + _randomString(3);
                }
                else
                {
                    PHI.pcCommand.Parameters.Add(PhpCommandParameters.KNAME, "Ritter" + _randomString(3));
                }

                //_PH.PostItems.Add(PHI);
                _PH.PostItemsAdd(PHI);
            }

            _PH.StartPosting();

                //foreach (HireKnightItem HKI in _ocKnightsToHireList)
                //{
                //    PostHandlerItem PHI = new PostHandlerItem(_KRNL.InternalUID);
                //    PHI.pcCommand = PhpCommandGenerator.GetPhpCommand(_KRNL.EC, PhpCommands.hireKnight, _KK2VM.ServerId, _KK2VM.SelectedUser.FbUid);

                //    //set parameters
                //    if (PHI.pcCommand.Parameters.ContainsKey(PhpCommandParameters.FRIEND_PF_ID))
                //    {
                //        PHI.pcCommand.Parameters[PhpCommandParameters.FRIEND_PF_ID] = HKI.SeekKnight.Uid.ToString();
                //    }
                //    else
                //    {
                //        PHI.pcCommand.Parameters.Add(PhpCommandParameters.FRIEND_PF_ID, HKI.SeekKnight.Uid.ToString());
                //    }

                //    if (PHI.pcCommand.Parameters.ContainsKey(PhpCommandParameters.CID))
                //    {
                //        PHI.pcCommand.Parameters[PhpCommandParameters.CID] = SelectedCity.CityID.ToString();
                //    }
                //    else
                //    {
                //        PHI.pcCommand.Parameters.Add(PhpCommandParameters.CID, SelectedCity.CityID.ToString());
                //    }

                //    _PH.PostItems.Add(PHI);
            //_PH.PostItemsAdd(PHI);
                //}

                //_PH.StartPosting();
            //}
            //catch (Exception ex)
            //{
            //    _KRNL.EC.AddException(ex, this.ToString(), _KRNL.EC.Tools.GetCurrentMethodName());
            //}
        }

        /// <summary>
        /// 
        /// </summary>
        /// <history>created  06.06.2012</history>
        private void _initRandom()
        {
            DateTime date1 = new DateTime(1970, 1, 1);  //Refernzdatum (festgelegt)
            TimeSpan ts = new TimeSpan(DateTime.Now.Ticks - date1.Ticks);  // das Delta ermitteln
            _RND = new Random(Convert.ToInt32(ts.TotalSeconds));
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="Length"></param>
        /// <returns></returns>
        /// <history>modified 06.06.2012</history>
        private string _randomString(Int64 Length)
        {
            StringBuilder Temp = new StringBuilder();
            for (Int64 i = 0; i < Length; i++)
            {
                Temp.Append(Convert.ToChar(((byte)_RND.Next(65, 90))).ToString());
            }
            return Temp.ToString();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <history>created  14.03.2012</history>
        private void _checkCanHireKnights()
        {
            //if (!_fHiringKnights &&
            //    PhpCommandGenerator.IsInitialized &&
            //    _KK2VM.SelectedUser != null &&
            //    _KK2VM.ServerId > 0 &&
            //    (SelectedCity != null || SelectedCityId != "") &&
            //    _ocKnightsToHireList.Count > 0)
            if (!_PH.PostingActive &&
                PhpCommandGenerator.IsInitialized &&
                _KK2VM.SelectedUser != null &&
                _KK2VM.ServerId > 0 &&
                (SelectedCity != null || SelectedCityId != "") &&
                _ocKnightsToHireList.Count > 0)
            {
                _changeCanHireKnights(true);
            }
            else
            {
                _changeCanHireKnights(false);
            }
        }

        #region UI-Invokes
        /// <summary>
        /// 
        /// </summary>
        /// <history>created  27.02.2012</history>
        private void _BeginHiring()
        {
            _DISP.Invoke((Action)delegate
            {
                _fHiringKnights = true;
                OnPropertyChanged("CanHireKnights");
                OnPropertyChanged("HireKnights");
            });
        }

        /// <summary>
        /// 
        /// </summary>
        /// <history>created  27.02.2012</history>
        private void _EndHiring()
        {
            _DISP.Invoke((Action)delegate
            {
                _fHiringKnights = false;
                OnPropertyChanged("CanHireKnights");
                OnPropertyChanged("HireKnights");
            });
        }

        /// <summary>_clearKnights</summary>
        /// <history>created  27.02.2012</history>
        private void _clearKnights()
        {
            _DISP.Invoke((Action)delegate
            {
                _ocKnightsToHireList.Clear();
                OnPropertyChanged("KnightsToHireList");
            });
        }

        /// <summary>_AddKnight</summary>
        /// <param name="HKI"></param>
        /// <history>created  27.02.2012</history>
        private void _AddKnight(
            HireKnightItem HKI)
        {
            _DISP.Invoke((Action)delegate
            {
                _ocKnightsToHireList.Add(HKI);
                OnPropertyChanged("KnightsToHireList");
            });
        }

        /// <summary></summary>
        /// <history>created  28.02.2012</history>
        private void _clearCities()
        {
            _DISP.Invoke((Action)delegate
            {
                _ocCityList.Clear();
                SelectedCity = null;
                OnPropertyChanged("Cities");
                OnPropertyChanged("SelectedCity");
            });
        }

        /// <summary></summary>
        /// <param name="CI"></param>
        /// <history>created  28.02.2012</history>
        private void _AddCity(
            CityItem CI)
        {
            _DISP.Invoke((Action)delegate
            {
                _ocCityList.Add(CI);
                OnPropertyChanged("Cities");
            });
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="CanHireKnights"></param>
        /// <history>created  14.03.2012</history>
        private void _changeCanHireKnights(
            bool CanHireKnights)
        {
            if (_fCanHireKnights != CanHireKnights)
            {
                _DISP.Invoke((Action)delegate
                {
                    _fCanHireKnights = CanHireKnights;
                    OnPropertyChanged("CanHireKnights");
                    OnPropertyChanged("HireKnights");
                });
            }
        }
        #endregion
        #endregion



        #region interface
        #region properties
        /// <summary>
        /// 
        /// </summary>
        /// <history>created  08.06.2012</history>
        public PostHandler PH { get { return _PH; } }

        /// <summary>
        /// 
        /// </summary>
        /// <history>created  28.02.2012</history>
        public ObservableCollection<CityItem> Cities { get { return _ocCityList; } }

        /// <summary>
        /// 
        /// </summary>
        /// <history>created  28.02.2012</history>
        public CityItem SelectedCity
        {
            get { return _selectedCity; }
            set
            {
                _selectedCity = value;
                if (_selectedCity != null)
                {
                    SelectedCityId = _selectedCity.CityID.ToString();
                    OnPropertyChanged("SelectedCityId");
                }
                _checkCanHireKnights();
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <history>created  06.06.2012</history>
        public string SelectedCityId
        {
            get { return _strSelectedCityId; }
            set { _strSelectedCityId = value; _checkCanHireKnights(); }
        }


        /// <summary>
        /// 
        /// </summary>
        /// <history>created  26.02.2012</history>
        public ICommand HireKnights
        {
            get
            {
                if(_rcHireKnights == null)
                {
                    _rcHireKnights = new RelayCommand(
                        param => this._hireKnights(),
                        param => this.CanHireKnights);
                }
                return _rcHireKnights;
            }
        }
        public bool CanHireKnights { get { return _fCanHireKnights; } }

        /// <summary>
        /// 
        /// </summary>
        /// <history>created  27.02.2012</history>
        public int KnightsToHire { get { return _intKnightsToHire; } set { _intKnightsToHire = value; _createHireList(); } }

        /// <summary>
        /// 
        /// </summary>
        /// <history>created  27.02.2012</history>
        public ObservableCollection<HireKnightItem> KnightsToHireList { get { return _ocKnightsToHireList; } }
        #endregion

        #region methods
        #endregion
        #endregion
    }
}
